#ifndef TREE_STRUCTURES_H
#define TREE_STRUCTURES_H

#include "StorageManager/Record.h"

#include <iostream>
#include <limits.h>
#define INDEXID 0
#define LEAFID 1

/**********************************************************************
 * The following class definitions are for creating the different page
 * objects in an index tree
 ***********************************************************************/

//Generic node that contains all the common attributes of a node in an index
class Node {
protected:
const int d;

public:
	int q;
	int *keys;
	int id;
	int highKey;

	Node(): d(64) {
		keys=new int[d+1];
	}
	Node(int d): d(d) {
		keys=new int[d+1];
	}

	bool isNodeFull();
	void printKeysNode();
};

//A specific Node used for implementing internal nodes
class IndexNode : public Node {
public:
	Node** nodePtrs;
	Node *nextNode;

	IndexNode(): Node() {
		nodePtrs = new Node *[66];
		q=0;
		id = INDEXID;
		nextNode = NULL;
		highKey = INT_MAX;
	}
	IndexNode(int d): Node(d) {
		nodePtrs = new Node *[d+2];
		q=0;
		id = INDEXID;
		nextNode = NULL;
		highKey = INT_MAX;
	}

	void insertKeyInIndex(IndexNode *, int );
	IndexNode * splitIndexNode(int);
};

//A specific Node used for implementing leaf nodes
class LeafNode : public Node {
public:
	Record** records;
	LeafNode *nextLeaf;

	LeafNode(): Node() {
		records = new Record *[64];
		q=0;
		id = LEAFID;
		nextLeaf = NULL;
		highKey = INT_MAX;
	}
	LeafNode(int d): Node(d) {
		records = new Record *[d];
		q=0;
		id = LEAFID;
		nextLeaf = NULL;
		highKey = INT_MAX;
	}

	Record * returnRecordInLeaf(int);
	IndexNode * splitLeafNode(int);
	int insertRecordInLeaf(int, Record *);
};

//This element is used to store the root on the stack for insertRecord()
struct stackElement {
	Node *node;
	int index;
};

#endif
